package com.pzhu.user.rpc.server;

import com.google.protobuf.Empty;
import com.pzhu.base.common.utils.exceptions.Assert;
import com.pzhu.user.api.MenuApi;
import com.pzhu.user.api.MenuServiceGrpc;
import com.pzhu.user.domain.dto.converter.MenuDtoConverter;
import com.pzhu.user.domain.ro.MenuCreateRO;
import com.pzhu.user.domain.ro.MenuSearchRO;
import com.pzhu.user.domain.ro.MenuUpdateRO;
import com.pzhu.user.domain.vo.MenuSearchVO;
import com.pzhu.user.service.impl.MenuService;
import io.grpc.stub.StreamObserver;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import net.devh.boot.grpc.server.service.GrpcService;

@GrpcService
@RequiredArgsConstructor
public class MenuServer extends MenuServiceGrpc.MenuServiceImplBase {

    private final MenuService menuService;

    private final MenuDtoConverter menuDtoConverter;

    @Override
    public void createMenu(MenuApi.MenuCreateRequest request, StreamObserver<MenuApi.MenuCreateResponse> responseObserver) {
        try {
            MenuApi.MenuCreateDTO menuCreateDTO = request.getMenu();
            MenuCreateRO menuCreateRO = menuDtoConverter.convert(menuCreateDTO);
            Long menuId = menuService.save(menuCreateRO);
            
            MenuApi.MenuCreateResponse.Builder builder = MenuApi.MenuCreateResponse.newBuilder();
            Optional.ofNullable(menuId).ifPresent(builder::setMenuId);
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void getMenuById(MenuApi.GetMenuRequest request, StreamObserver<MenuApi.MenuResponse> responseObserver) {
        try {
            Long menuId = request.getMenuId();
            MenuSearchVO menuSearchVO = menuService.info(menuId);
            Assert.assertNotNull(menuSearchVO, "菜单不存在");
            
            MenuApi.MenuDTO menuDTO = menuDtoConverter.toDTO(menuSearchVO);
            MenuApi.MenuResponse.Builder builder = MenuApi.MenuResponse.newBuilder();
            responseObserver.onNext(builder.setMenu(menuDTO).build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void getMenuByCode(MenuApi.GetMenuByCodeRequest request, StreamObserver<MenuApi.MenuResponse> responseObserver) {
        try {
            String menuCode = request.getMenuCode();
            MenuSearchVO menuSearchVO = menuService.searchOne(MenuSearchRO.builder().menuCode(menuCode).build());
            Assert.assertNotNull(menuSearchVO, "菜单不存在");
            
            MenuApi.MenuDTO menuDTO = menuDtoConverter.toDTO(menuSearchVO);
            MenuApi.MenuResponse.Builder builder = MenuApi.MenuResponse.newBuilder();
            responseObserver.onNext(builder.setMenu(menuDTO).build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void updateMenu(MenuApi.UpdateMenuRequest request, StreamObserver<MenuApi.MenuResponse> responseObserver) {
        try {
            Long menuId = request.getMenuId();
            MenuApi.MenuUpdateDTO menuUpdateDTO = request.getMenu();
            MenuUpdateRO menuUpdateRO = menuDtoConverter.convertUpdate(menuUpdateDTO);
            
            boolean result = menuService.update(menuId, menuUpdateRO);
            Assert.assertTrue(result, "更新菜单失败");
            
            MenuSearchVO menuSearchVO = menuService.info(menuId);
            MenuApi.MenuDTO menuDTO = menuDtoConverter.toDTO(menuSearchVO);
            MenuApi.MenuResponse.Builder builder = MenuApi.MenuResponse.newBuilder();
            responseObserver.onNext(builder.setMenu(menuDTO).build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void deleteMenu(MenuApi.DeleteMenuRequest request, StreamObserver<Empty> responseObserver) {
        try {
            Long menuId = request.getMenuId();
            boolean result = menuService.removeById(menuId);
            Assert.assertTrue(result, "删除菜单失败");
            
            responseObserver.onNext(Empty.newBuilder().build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void batchDeleteMenus(MenuApi.BatchDeleteMenusRequest request, StreamObserver<Empty> responseObserver) {
        try {
            List<Long> menuIds = request.getMenuIdsList();
            boolean result = menuService.removeByIds(menuIds);
            Assert.assertTrue(result, "批量删除菜单失败");
            
            responseObserver.onNext(Empty.newBuilder().build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void getAllMenus(MenuApi.GetAllMenusRequest request, StreamObserver<MenuApi.GetAllMenusResponse> responseObserver) {
        try {
            List<MenuSearchVO> menus = menuService.getAllMenus();
            List<MenuApi.MenuDTO> menuDTOs = menus.stream()
                    .map(menuDtoConverter::toDTO)
                    .collect(Collectors.toList());
            
            MenuApi.GetAllMenusResponse.Builder builder = MenuApi.GetAllMenusResponse.newBuilder();
            builder.addAllMenus(menuDTOs);
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void getUserMenus(MenuApi.GetUserMenusRequest request, StreamObserver<MenuApi.GetUserMenusResponse> responseObserver) {
        try {
            Long userId = request.getUserId();
            List<MenuSearchVO> userMenus = menuService.getUserMenus(userId);
            List<MenuApi.MenuDTO> menuDTOs = userMenus.stream()
                    .map(menuDtoConverter::toDTO)
                    .collect(Collectors.toList());
            
            MenuApi.GetUserMenusResponse.Builder builder = MenuApi.GetUserMenusResponse.newBuilder();
            builder.addAllMenus(menuDTOs);
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }

    @Override
    public void getRoleMenus(MenuApi.GetRoleMenusRequest request, StreamObserver<MenuApi.GetRoleMenusResponse> responseObserver) {
        try {
            Long roleId = request.getRoleId();
            List<MenuSearchVO> roleMenus = menuService.getRoleMenus(roleId);
            List<MenuApi.MenuDTO> menuDTOs = roleMenus.stream()
                    .map(menuDtoConverter::toDTO)
                    .collect(Collectors.toList());
            
            MenuApi.GetRoleMenusResponse.Builder builder = MenuApi.GetRoleMenusResponse.newBuilder();
            builder.addAllMenus(menuDTOs);
            responseObserver.onNext(builder.build());
            responseObserver.onCompleted();
        } catch (Exception e) {
            responseObserver.onError(e);
        }
    }
}